/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package TimeRecording.TimeClockServer;

import TimeRecording.TimeClockServer.enums.TxOrRx;
import TimeRecording.TimeClockServer.dtos.TxRxBytes;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * The majority of this class will run in its own thread and it will be
 * responsible for reading data from the clock terminal and forwarding these
 * messages to two separate channels.  The first of these channels is a GUI
 * observer; this will be managed via publish/process methods of the SwingWorker
 * class.  The second channel will be a synchronised message pipe that will feed
 * into logic responsible for managing application level communications with the
 * clock terminal.
 *
 * Note that management of the socket and the buffer are external to this task;
 * it is the responsibility of the clock server as a whole to manage creation
 * and destruction of that socket.
 *
 * @author dpatchett
 */
public class ClockReceiver extends Thread {

    // The maximum number of bytes read in a single I/O operation;
    // bigger messages can be accomodated via multiple I/O reads.
    private final static int BUFFER_SIZE = 0x1000;

    // The server class that hosts the RX buffer, that (optionally) logs low-
    // level message receipt and that manages the TCP/IP socket through which
    // this class communicates with the clock terminal
    private ClockServer parent;

    private InputStream inStream;

    /**
     * A simple constructor for the receiver that supplied its incoming
     * interface (a TCP/IP socket to the clock terminal) and its outgoing
     * interface (a message buffer in which to pipe bytes).
     *
     * @param clientSocket
     * @param buffer
     * @throws IOException
     */
    public ClockReceiver(ClockServer parent, InputStream inStream) {
        this.parent = parent;
        this.inStream = inStream;
    }

    /**
     * The main body of the receiver (it doesn't do a lot!)  It simply reads
     * data from TCP/IP socket at pipes it into the waiting buffer.  A secondary
     * function is the logging of bytes to a parent thread for display only
     * purposes.
     *
     * Depending upon how the clock terminal sends data, it is quite possible
     * that a single array of bytes might contain multiple, partial or single
     * messages.
     *
     * Note that although extending the swing worker class, this thread does not
     * have a fixed lifespan; it will exit only when interrupted but more likely
     * when the TCP/IP socket to the clock terminal has closed.
     *
     * @return nothing (method will only return when the socket closes)
     * @throws Exception
     */

    @Override
    public void run() {

        int byteCount = 0;
        byte[] inBytes = new byte[BUFFER_SIZE];

        try {
            do {
                byteCount = inStream.read(inBytes);
                if (byteCount > 0) {
                    parent.getRxBuffer().addBytes(inBytes, byteCount);
                    parent.deferredLogTxRxBytes(new TxRxBytes(
                            inBytes, byteCount, null, TxOrRx.RX));
                }
                
            } while (byteCount != -1 && !interrupted());

        } catch (SocketTimeoutException ex) {
            interrupt();

        } catch (IOException ex) {
            Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
        }
    }
}